package msg

import (
	"fmt"
	"github.com/jinzhu/gorm"
	"strconv"
	"talent.com/agency_im/common/utils"
	"talent.com/agency_im/conf"
	"talent.com/agency_im/conf/g"
	"time"
)

//////////////////////////////////////////////////////////////////////////////
///////////////////  消息相关功能 //////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// 插入新消息
func InsertMessage(message *Message) (*Message, error) {
	message.TopicID = GetTopicID(message.TopicType, message.SourceID, message.TargetID)

	// 检查ClientID消息是否存在
	if result := g.ORM.Where("topic_id = ? and source_id = "+
		"? and client_id = ?", message.TopicID, message.SourceID, message.ClientID).First(message); result.RecordNotFound() {
		err := g.ORM.Create(message).Error
		return message, err
	} else {
		if result.Error != nil {
			return nil, result.Error
		} else {
			return message, nil
		}
	}
}

// 获取某个会话的最后一条消息
func GetLastMessageByTopicID(topicID string) (*Message, error) {
	var (
		message Message
		err     error
	)

	if err = g.ORM.Where("topic_id = ?", topicID).Order("id desc").First(&message).Error; err != nil {
		if gorm.IsRecordNotFoundError(err) {
			return nil, nil
		} else {
			return nil, err
		}
	} else {
		return &message, nil
	}
}

// 获取SourceID用户给TargetID用户发送的最后一条消息
func GetLastMessageBySourceID(SourceID uint64, TargetID uint64) (*Message, error) {
	var (
		message Message
		err     error
	)

	if err = g.ORM.Where("source_id = ? and target_id = ?", SourceID, TargetID).Order("id desc").First(&message).Error; err != nil {
		if gorm.IsRecordNotFoundError(err) {
			return nil, nil
		} else {
			return nil, err
		}
	} else {
		return &message, nil
	}
}

// 获取TargetID用户给SourceID用户发送的第一条未回复的消息
func GetOldestMessageBySourceID(SourceID uint64, TargetID uint64) (*Message, error) {
	var (
		message  Message
		err      error
		OldestId uint64
	)
	m, _ := GetLastMessageBySourceID(SourceID, TargetID)
	if m != nil {
		OldestId = m.ID
	}

	if err = g.ORM.Where("source_id = ? and target_id = ? and id > ?", TargetID, SourceID, OldestId).Order("id").First(&message).Error; err != nil {

		if gorm.IsRecordNotFoundError(err) {
			return nil, nil
		} else {
			return nil, err
		}
	} else {
		return &message, nil
	}
}

// 拉取某个会话中的消息列表，按消息产生时间递增时间拉取
func FetchOldestMessagesInTopic(topicID string, lastMsgID uint64, limit int) ([]Message, error) {
	var (
		messages []Message
		err      error
	)
	if err = g.ORM.Limit(limit).Order("id asc").Where("topic_id = ? and id > ?", topicID, lastMsgID).Find(&messages).Error; err != nil {
		if gorm.IsRecordNotFoundError(err) {
			return messages, nil
		}
		return nil, err
	} else {
		return messages, nil
	}
}

// 拉取某个会话中的消息列表，按消息产生时间递减时间拉取, 即先拉取最新的
func FetchLatestMessagesInTopic(topicID string, lastMsgID uint64, limit int) ([]Message, error) {
	var (
		messages []Message
		err      error
	)

	if limit < 1 || limit > 50 {
		limit = 50
	}

	query := g.ORM.Limit(limit).Order("id desc").Where("topic_id = ?", topicID)
	if lastMsgID > 0 {
		query = query.Where("id < ?", lastMsgID)
	}

	if err = query.Find(&messages).Error; err != nil {
		if gorm.IsRecordNotFoundError(err) {
			return messages, nil
		}
		return nil, err
	} else {
		return messages, nil
	}
}

// 获取某个用户是否有未读消息
func HasUnreadMessages(uid uint64) (bool, error) {
	var (
		result int
		err    error
	)

	if err = g.ORM.Model(&MessageTopic{}).Where("user_id = ? and max_msg_id > read_msg_id", uid).Count(&result).Error; err != nil {
		return false, err
	}
	return result > 0, nil
}

//////////////////////////////////////////////////////////////////////////////
///////////////////  会话相关功能 //////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

func GetTopicByID(ID uint64) (*MessageTopic, error) {
	var (
		topic MessageTopic
		err   error
	)
	if err = g.ORM.Where("id = ?", ID).First(&topic).Error; err != nil {
		return nil, err
	} else {
		return &topic, nil
	}
}

// 判断两个用户之间是否有会话记录
func HasExistPrivateTopic(sourceID uint64, targetID uint64) (bool, error) {
	topicID := GetTopicID(int8(TOPIC_TYPE_PRIVATE), sourceID, targetID)
	var (
		result int
		err    error
	)
	if err = g.ORM.Model(MessageTopic{}).Where("topic_id = ?", topicID).Count(&result).Error; err != nil {
		return false, err
	} else {
		return result > 0, nil
	}
}

// 工具方法：topicID生成
func GetTopicID(topicType int8, sourceID uint64, targetID uint64) string {
	var topicID string
	if topicType == int8(TOPIC_TYPE_PRIVATE) {
		topicID = fmt.Sprintf("%d-%d", utils.Min(sourceID, targetID), utils.Max(sourceID, targetID))
	} else {
		topicID = strconv.Itoa(int(targetID))
	}
	return topicID
}

// 更新用户某个会话已读消息最大游标
func UpdateTopicMaxMsgIDAndIsReplied(topic *MessageTopic) (bool, error) {
	if topic.ID > 0 || topic.MaxMsgID == 0 {
		return false, nil
	}

	rowsAffected := g.ORM.Model(MessageTopic{}).Where("topic_id = ? and user_id = ? and max_msg_id < ?", topic.TopicID, topic.UserID, topic.MaxMsgID).Updates(map[string]interface{}{"max_msg_id": topic.MaxMsgID, "is_replied": topic.IsReplied}).RowsAffected
	if rowsAffected > 0 {
		return true, nil
	} else {
		var existTopic MessageTopic
		if g.ORM.Where("topic_id = ? and user_id = ?", topic.TopicID, topic.UserID).First(&existTopic).RecordNotFound() {
			if result := g.ORM.Create(topic); result.Error != nil {
				return false, result.Error
			} else {
				return true, nil
			}
		} else {
			return false, nil
		}
	}

}

// 获取某个关联所有的包含未读消息的会话列表
func GetUnreadTopicsByTopicID(topicID string) ([]MessageTopic, error) {
	var (
		msgTopics []MessageTopic
		err       error
	)
	if err = g.ORM.Where("topic_id = ? and max_msg_id > read_msg_id", topicID).Find(&msgTopics).Error; err != nil {
		return nil, err
	} else {
		return msgTopics, nil
	}
}

// 获取用户的所有未读会话列表
func GetUnreadTopicsByUserID(userID uint64) ([]MessageTopic, error) {
	var (
		msgTopics []MessageTopic
		err       error
	)
	if err = g.ORM.Where("user_id = ? and max_msg_id > read_msg_id", userID).Find(&msgTopics).Error; err != nil {
		return nil, err
	} else {
		return msgTopics, nil
	}
}

// 更新用户的某个会话已读消息游标
func UpdateTopicReadMsgID(userID uint64, topicID string, readMsgID uint64) (bool, error) {
	result := g.ORM.Model(MessageTopic{}).Where("topic_id = ? and user_id = ? and read_msg_id < ?", topicID, userID, readMsgID).Updates(MessageTopic{ReadMsgID: readMsgID})
	if result.Error != nil {
		return false, result.Error
	}
	if result.RowsAffected > 0 {
		return true, nil
	}
	return false, nil
}

// 综合查询会话列表
func ListTopics(ID uint64, sourcePlatformID uint64, sourceIDs []uint64, targetID uint64, startUpdatedAt time.Time, endUpdatedAt time.Time, isReplied int, pageNo int, pageSize int) (int, []MessageTopic, error) {
	var (
		topics []MessageTopic
		total  int
		err    error
	)

	if pageNo < 1 {
		pageNo = 1
	}

	if pageSize < 1 || pageSize > 50 {
		pageSize = 30
	}
	result := g.ORM.Order("updated_at desc").Where("user_id <> ? and target_id <> ?", conf.ServerConfig().Pay.PayOperatorID, conf.ServerConfig().Pay.PayOperatorID)
	if ID > 0 {
		result = result.Where("id = ?", ID)
	}
	if sourcePlatformID > 0 {
		result = result.Where("user_platform_id = ?", sourcePlatformID)
	}
	if len(sourceIDs) > 0 {
		result = result.Where("user_id in (?)", sourceIDs)
	}
	if targetID > 0 {
		result = result.Where("target_id = ?", targetID)
	}
	if !startUpdatedAt.IsZero() {
		result = result.Where("updated_at > ?", startUpdatedAt)
	}
	if !endUpdatedAt.IsZero() {
		result = result.Where("updated_at <= ?", endUpdatedAt)
	}
	if isReplied != -1 {
		if isReplied == 1 {
			result = result.Where("is_replied = ?", 1)
		} else {
			result = result.Where("is_replied = ?", 0)
		}
	}

	if err = result.Model(&MessageTopic{}).Count(&total).Error; err != nil {
		return 0, nil, err
	} else {
		if err = result.Offset((pageNo - 1) * pageSize).Limit(pageSize).Find(&topics).Error; err != nil {
			return 0, nil, err
		} else {
			return total, topics, nil
		}
	}
}
